#COMPILE EXE #DIM ALL #RESOURCE "zrl.pbr" #INCLUDE ONCE "win32api.inc" #INCLUDE ONCE "inc\conspawn.inc" #INCLUDE ONCE "inc\savepos.inc" #INCLUDE ONCE "inc\pb_ftp.inc" #INCLUDE ONCE "inc\ini.inc" #INCLUDE ONCE "inc\centermsgbox.inc" '------------------------ $VER = "1.0" '------------------------ %IDC_GRAPHIC1 = 1001 %IDC_LABEL1 = 1002 %IDC_LABEL2 = 1003 %IDC_ICOCON = 1004 %IDC_ICOINI = 1005 %IDC_ICOPHP = 1006 %IDC_ICOLOG = 1007 '------------------------ GLOBAL g_hDlg AS DWORD GLOBAL g_FntN AS DWORD GLOBAL g_FntU AS DWORD GLOBAL g_FntS AS DWORD GLOBAL g_ftpUL AS LONG GLOBAL g_status AS LONG GLOBAL g_stuck AS LONG GLOBAL g_msg AS STRING GLOBAL g_zParam AS STRING GLOBAL g_phpSrc AS STRING GLOBAL g_phpRpl AS STRING GLOBAL g_ftpTgt AS STRING GLOBAL g_ftpSrv AS STRING GLOBAL g_ftpUsr AS STRING GLOBAL g_ftpPwd AS STRING GLOBAL g_AcoTkn AS STRING GLOBAL g_editor AS STRING '--------------------------------------------------------------------- MACRO DlgBgCol = GETSYSCOLOR(%COLOR_BTNFACE) MACRO Npp_x86 = RTRIM$(ENVIRON$("ProgramFiles"), "\") + "\Notepad++\" MACRO Npp_w64 = RTRIM$(ENVIRON$("ProgramW6432"), "\") + "\Notepad++\" MACRO This_Bat = ENVIRON$("APPDATA") + "\" + EXE.NAME$ + ".bat" '--------------------------------------------------------------------- '------------------------------------------------------------------------------ ' ** Main Application Entry Point ** '------------------------------------------------------------------------------ FUNCTION PBMAIN () AS LONG LOCAL npp AS STRING ' Reset some files KILL EXE.NAME$ + ".log" KILL This_Bat ' Find Notepad++ if installed on the system npp = "notepad++.exe" g_editor = DIR$(Npp_w64 + npp) : DIR$ CLOSE ' try Npp_w64 first IF g_editor <> "" THEN g_editor = Npp_w64 + npp + $SPC ELSE g_editor = DIR$(Npp_x86 + npp) : DIR$ CLOSE ' then try Npp_x86 IF g_editor <> "" THEN g_editor = Npp_x86 + npp + $SPC ELSE g_editor = "notepad " ' none found: use windows notepad END IF END IF ' Start dialog ShowDIALOG() END FUNCTION '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ SUB CON_HANDLER(BYVAL txt AS STRING) STATIC otxt AS STRING LOCAL zurl, buf AS STRING LOCAL i, ff, hSocket AS LONG IF txt = "" THEN ' zrok failure (fatal) g_msg = "zrok internal error" LogMe g_msg LogMe "Last zrok content received:" IF TRIM$(otxt) = "" THEN ' nothing happened > try to learn a little more ff = FREEFILE OPEN "ztemp.bat" FOR OUTPUT AS #ff PRINT #ff, "zrok.exe share public localhost:80 > ztemp.out 2>&1" CLOSE #ff SHELL "ztemp.bat", 0 KILL "ztemp.bat" ff = FREEFILE OPEN "ztemp.out" FOR BINARY AS #ff GET$ #ff, LOF(#ff), otxt CLOSE #ff KILL "ztemp.out" IF INSTR(otxt, "shareUnauthorized") > 0 THEN g_stuck = 1 END IF LogMe TRIM$(otxt) '>>>>><<<<<' g_status = 9 '>>>>><<<<<' GOTO skip END IF IF g_status <> 1 THEN GOTO skip ' only continue if zrok is in starting phase ' Try to get url assigned by zrok i = INSTR(txt, "http") IF i = 0 THEN GOTO skip ' url not assigned yet > wait txt = MID$(txt, i) i = INSTR(txt, ".io") IF i = 0 THEN GOTO skip ' url not fully assigned yet > wait some more zurl = LEFT$(txt, i+LEN(".io")-1) LogMe "zrok correctly connected and serving at " + zurl g_msg = zurl ' No ftp upload requested > we're all good! IF ISFALSE g_ftpUL THEN LogMe "ftp upload disabled by user > skipping" '>>>>><<<<<' g_status = 2 '>>>>><<<<<' GOTO skip END IF ' prepare proxy page for upload IF NOT EXISTS(g_phpSrc) THEN LogMe "ftp upload error: template " + $DQ + g_phpSrc + $DQ + " not found" g_msg += $CR + "service running but ftp uload failed" '>>>>><<<<<' g_status = 7 ' semi-error: zrok running but ftp upload failed '>>>>><<<<<' GOTO skip END IF ' bufferize template ff = FREEFILE OPEN g_phpSrc FOR BINARY AS #ff GET$ #ff, LOF(#ff), buf CLOSE #ff IF INSTR(buf, g_phpRpl) = 0 THEN LogMe "ftp upload error: replaced string " + $DQ + g_phpRpl + $DQ _ + " not found in template " + $DQ + g_phpSrc + $DQ g_msg += $CR + "service running but ftp uload failed" '>>>>><<<<<' g_status = 7 ' semi-error: zrok running but ftp upload failed '>>>>><<<<<' GOTO skip END IF ' fill template into temp file REPLACE g_phpRpl WITH zurl IN buf KILL "zrltmp.php" ff = FREEFILE OPEN "zrltmp.php" FOR BINARY AS #ff PUT$ #ff, buf CLOSE #ff ' upload it to ftp server hSocket = ftpConnect(g_ftpSrv, g_ftpUsr, g_ftpPwd) IF hSocket = %INVALID_SOCKET THEN LogMe "ftp upload error: could not connect to " + g_ftpSrv _ + " - invalid credentials ?" g_msg += $CR + "service running but ftp uload failed" '>>>>><<<<<' g_status = 7 ' semi-error: zrok running but ftp upload failed '>>>>><<<<<' GOTO skip END IF ftpPutFile hSocket, 0, g_ftpSrv, g_ftpTgt, "zrltmp.php" ftpQuit hSocket KILL "zrltmp.php" LogMe "Correctly changed zrok url in " + $DQ + g_phpSrc + $DQ _ + " and uploaded it to " + g_ftpTgt + " @" + g_ftpSrv ' all done '>>>>><<<<<' g_status = 2 '>>>>><<<<<' skip: otxt = txt END SUB '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' ** CallBacks ** '------------------------------------------------------------------------------ CALLBACK FUNCTION ProcDialog() STATIC blink AS LONG STATIC zconv AS LONG LOCAL ctl, i, ff AS LONG LOCAL e AS STRING CB_SAVEPOS CON_CALLBACK SELECT CASE AS LONG CB.MSG CASE %WM_INITDIALOG '---------------------------------------------- g_status = 0 IF NOT EXISTS("zrok launcher.ini") THEN ' First run > create ini and php MakeIni "zrok launcher.ini" MakePhp "zrok launcher.php" ?"This is your first time running zrok launcher."+$CR _ +$CR _ +"Click OK to open the settings file in an editor:"+$CR _ +"make sure to change the settings as needed, then"+$CR _ +"re-launch zrok launcher.", %MB_ICONINFORMATION, EXE.NAME$ ctl = SHELL(g_editor + $DQ + "zrok launcher.ini" + $DQ) DIALOG END CB.HNDL EXIT FUNCTION ELSE ff = FREEFILE ' Following runs: simplify ini OPEN "zrok launcher.ini" FOR BINARY AS #ff GET$ #ff, LOF(#ff), e CLOSE #ff IF INSTR(e, "first time") > 0 THEN i = INSTR(e, "zrok launcher") IF i > 0 THEN i = INSTR(i, e, $CR) e = "# Make sure the following settings are correct: " + MID$(e, i) KILL "zrok launcher.ini" ff = FREEFILE OPEN "zrok launcher.ini" FOR BINARY AS #ff PUT$ #ff, e CLOSE #ff END IF END IF END IF ' In any case: read ini GetIni() ' And prepare launch of zrok SetTimer CB.HNDL, 0, 200, 0 CASE %WM_TIMER '---------------------------------------------- IF CB.WPARAM <> 0 THEN EXIT FUNCTION IF g_status = 0 THEN ' Init: launch zrok g_status = 1 LogMe "Launching ""zrok.exe " + g_zParam + $DQ + " ..." CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, "launching zrok client" CONTROL SET FONT CB.HNDL, %IDC_LABEL1, g_FntN CONTROL SET COLOR CB.HNDL, %IDC_LABEL1, -1, -1 CON_LAUNCH CB.HNDL, "zrok.exe " + g_zParam, 0, 500 ELSEIF g_status = 1 THEN ' Zrok launching: blinking orange light blink = 1 - blink GRAPHIC ATTACH CB.HNDL, %IDC_GRAPHIC1, REDRAW GRAPHIC CLEAR DlgBgCol GRAPHIC WIDTH 2 IF ISTRUE blink THEN GRAPHIC ELLIPSE (8, 8) - (32, 32), %BLACK, %RGB_ORANGE GRAPHIC REDRAW ELSEIF g_status = 2 THEN ' Zrok running correctly in background - fixed green light KillTimer CB.HNDL, 0 CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, g_msg CONTROL SET FONT CB.HNDL, %IDC_LABEL1, g_FntU CONTROL SET COLOR CB.HNDL, %IDC_LABEL1, %RGB_DARKGREEN, -1 GRAPHIC ATTACH CB.HNDL, %IDC_GRAPHIC1, REDRAW GRAPHIC CLEAR DlgBgCol GRAPHIC WIDTH 2 GRAPHIC ELLIPSE (8, 8) - (32, 32), %BLACK, %RGB_LIME GRAPHIC REDRAW ELSEIF g_status = 7 THEN ' Zrok running but ftp upload failed (init) KillTimer CB.HNDL, 0 GRAPHIC ATTACH CB.HNDL, %IDC_GRAPHIC1, REDRAW GRAPHIC CLEAR DlgBgCol GRAPHIC WIDTH 2 GRAPHIC ELLIPSE (8, 8) - (32, 32), %BLACK, %YELLOW GRAPHIC REDRAW blink = 0 g_status = 8 SetTimer CB.HNDL, 0, 500, 0 ELSEIF g_status = 8 THEN ' Zrok running but ftp upload failed (permanent) blink = (blink + 1) MOD 8 GRAPHIC ATTACH CB.HNDL, %IDC_ICOLOG IF ISTRUE blink MOD 2 THEN GRAPHIC CLEAR DlgBgCol ELSE GRAPHIC RENDER "BMPLOG", (2,2)-(22,22) END IF IF blink = 1 THEN CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, PARSE$(g_msg, $CR, 1) CONTROL SET FONT CB.HNDL, %IDC_LABEL1, g_FntU CONTROL SET COLOR CB.HNDL, %IDC_LABEL1, %RGB_DARKGREEN, -1 DIALOG REDRAW CB.HNDL ELSEIF blink = 5 THEN CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, PARSE$(g_msg, $CR, 2) CONTROL SET FONT CB.HNDL, %IDC_LABEL1, g_FntN CONTROL SET COLOR CB.HNDL, %IDC_LABEL1, %RGB_ORANGE, -1 DIALOG REDRAW CB.HNDL END IF ELSEIF g_status = 9 THEN ' Fatal error - fixed red light (init) KillTimer CB.HNDL, 0 CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, "zrok internal error - see log" CONTROL SET FONT CB.HNDL, %IDC_LABEL1, g_FntN CONTROL SET COLOR CB.HNDL, %IDC_LABEL1, %RED, -1 GRAPHIC ATTACH CB.HNDL, %IDC_GRAPHIC1, REDRAW GRAPHIC CLEAR DlgBgCol GRAPHIC WIDTH 2 GRAPHIC ELLIPSE (8, 8) - (32, 32), %BLACK, %RED GRAPHIC REDRAW blink = 0 g_status = 10 SetTimer CB.HNDL, 0, 500, 0 IF ISTRUE g_stuck THEN IF CenterMessageBox (CB.HNDL, _ "zrok is stuck in a known error state." _ + $CRLF + $CRLF _ + "Do you want to reset it?" + $CRLF _ + "(you need to have filled your" + $CRLF _ + "acount_token in the .ini file)", _ EXE.NAME$, %MB_ICONWARNING OR %MB_YESNO) = %IDYES THEN LogMe "resetting zrok with account token " + g_AcoTkn CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, "resetting zrok... pls be patient" ff = FREEFILE OPEN "zrok_reset.bat" FOR OUTPUT AS #ff PRINT #ff, "zrok disable" PRINT #ff, "zrok enable " + g_AcoTkn CLOSE #ff SHELL "zrok_reset.bat", 0 KILL "zrok_reset.bat" LogMe "done. if the account token is correct, it should have worked" LogMe "zrok launcher needs to be restarted" CONTROL SET TEXT CB.HNDL, %IDC_LABEL1, "zrok has been reset - see log" CenterMessageBox CB.HNDL, "Zrok has been reset" _ + $CR + $CR _ + "Click OK to restart zrok launcher", _ EXE.NAME$, %MB_ICONINFORMATION ' Create batch file to restart ourselves ff = FREEFILE OPEN This_Bat FOR OUTPUT AS #ff PRINT #ff, "TimeOut 1" PRINT #ff, "start " + $DQ+$DQ + $SPC + $DQ+EXE.FULL$+$DQ CLOSE #ff ff = SHELL(This_Bat, 6) ' minimized without focus ' Close ourselves PostMessage CB.HNDL, %WM_SYSCOMMAND, %SC_CLOSE, 0 SLEEP 500 ExitProcess(12345) END IF END IF ELSEIF g_status = 10 THEN ' Fatal error - fixed red light (permanent) blink = 1 - blink GRAPHIC ATTACH CB.HNDL, %IDC_ICOLOG IF ISTRUE blink THEN GRAPHIC CLEAR DlgBgCol ELSE GRAPHIC RENDER "BMPLOG", (2,2)-(22,22) END IF END IF CASE %WM_SETCURSOR ' change cursor to link-hand when hovering over controls '---------------------------------------------- ctl = GetDlgCtrlId(CB.WPARAM) IF ctl = %IDC_LABEL1 OR ctl = %IDC_LABEL2 OR ctl = %IDC_GRAPHIC1 _ OR ctl = %IDC_ICOCON OR ctl = %IDC_ICOINI OR ctl = %IDC_ICOPHP _ OR ctl = %IDC_ICOLOG THEN IF ctl = %IDC_LABEL1 THEN CONTROL GET TEXT CB.HNDL, ctl TO e IF LEFT$(e, 4) <> "http" THEN EXIT FUNCTION END IF SetCursor LoadCursor(%NULL, BYVAL %IDC_HAND) SetWindowLong CB.HNDL, %dwl_msgresult, 1 FUNCTION = 1 END IF CASE %WM_COMMAND '---------------------------------------------- SELECT CASE AS LONG CB.CTL CASE %IDC_ICOCON ' view/hide zrok console window IF g_status <> 2 AND g_status <> 8 THEN EXIT FUNCTION zconv = 1 - zconv GRAPHIC ATTACH g_hDlg, %IDC_ICOCON GRAPHIC CLEAR DlgBgCol GRAPHIC RENDER IIF$(zconv,"BMPCOF","BMPCON"), (2,2)-(22,22) DIALOG POST CB.HNDL, %WM_APP + 1, 0, 0 CASE %IDC_ICOINI ' edit ini file ctl = SHELL(g_editor + $DQ + "zrok launcher.ini" + $DQ) CASE %IDC_ICOPHP ' edit php file ctl = SHELL(g_editor + $DQ + g_phpSrc + $DQ) CASE %IDC_ICOLOG ' view logs ctl = SHELL(g_editor + $DQ + EXE.NAME$ + ".log" + $DQ) CASE %IDC_LABEL1 CONTROL GET TEXT CB.HNDL, CB.CTL TO e IF LEFT$(e, 4) <> "http" THEN EXIT FUNCTION ShellExecute %NULL, "open", (e), "", "", %SW_SHOW CASE %IDC_LABEL2 ShellExecute %NULL, "open", "http://mougino.free.fr/freeware", "", "", %SW_SHOW END SELECT END SELECT END FUNCTION '------------------------------------------------------------------------------ '------------------------------------------------------------------------------ ' ** Dialogs ** '------------------------------------------------------------------------------ FUNCTION ShowDIALOG() AS LONG LOCAL lRslt AS LONG FONT NEW "MS Sans Serif", 8, 0, %ANSI_CHARSET TO g_FntN FONT NEW "MS Sans Serif", 8, 4, %ANSI_CHARSET TO g_FntU FONT NEW "", 6 TO g_FntS DIALOG NEW PIXELS, 0, EXE.NAME$, , , 240, 75, %WS_POPUP OR %WS_BORDER _ OR %WS_DLGFRAME OR %WS_CAPTION OR %WS_SYSMENU OR %WS_MINIMIZEBOX OR _ %WS_CLIPSIBLINGS OR %WS_VISIBLE OR %DS_MODALFRAME OR %DS_3DLOOK OR _ %DS_NOFAILCREATE OR %DS_SETFONT, %WS_EX_CONTROLPARENT OR %WS_EX_LEFT _ OR %WS_EX_LTRREADING OR %WS_EX_RIGHTSCROLLBAR, TO g_hDlg DIALOG SET ICON g_Hdlg, "AICO" CONTROL ADD GRAPHIC, g_hDlg, %IDC_GRAPHIC1, "", 0, 0, 32, 32 CONTROL ADD LABEL, g_hDlg, %IDC_LABEL1, "Ready.", 40, 12, 195, 16, %SS_NOTIFY CONTROL ADD GRAPHIC, g_hDlg, %IDC_ICOCON, "", 8+32*0, 50, 24, 24, %SS_NOTIFY GRAPHIC ATTACH g_hDlg, %IDC_ICOCON GRAPHIC RENDER "BMPCON", (2,2)-(22,22) CONTROL ADD GRAPHIC, g_hDlg, %IDC_ICOINI, "", 8+32*1, 50, 24, 24, %SS_NOTIFY GRAPHIC ATTACH g_hDlg, %IDC_ICOINI GRAPHIC RENDER "BMPINI", (2,2)-(22,22) CONTROL ADD GRAPHIC, g_hDlg, %IDC_ICOPHP, "", 8+32*2, 50, 24, 24, %SS_NOTIFY GRAPHIC ATTACH g_hDlg, %IDC_ICOPHP GRAPHIC RENDER "BMPPHP", (2,2)-(22,22) CONTROL ADD GRAPHIC, g_hDlg, %IDC_ICOLOG, "", 8+32*3, 50, 24, 24, %SS_NOTIFY GRAPHIC ATTACH g_hDlg, %IDC_ICOLOG GRAPHIC RENDER "BMPLOG", (2,2)-(22,22) lRslt = 8+32*3+24 CONTROL ADD LABEL, g_hDlg, 111, "v" + $VER, lRslt, 51, 236-lRslt, 8, %SS_NOTIFY OR %SS_RIGHT CONTROL SET COLOR g_hDlg, 111, RGB(80,80,80), -1 CONTROL SET FONT g_hDlg, 111, g_FntS CONTROL ADD LABEL, g_hDlg, %IDC_LABEL2, "http://mougino.free.fr", lRslt, 60, 236-lRslt, 16, %SS_NOTIFY OR %SS_RIGHT CONTROL SET COLOR g_hDlg, %IDC_LABEL2, %BLUE, -1 CONTROL SET FONT g_hDlg, %IDC_LABEL2, g_FntU CONTROL ADD LINE, g_hDlg, 999, "", 0, 49, 240, 1 DIALOG SHOW MODAL g_hDlg, CALL ProcDialog TO lRslt FUNCTION = lRslt END FUNCTION '------------------------------------------------------------------------------ '---------------------------------------------------- FUNCTION EXISTS(BYVAL f AS STRING) AS LONG LOCAL i AS LONG i = GETATTR(f) FUNCTION = (ERRCLEAR = 0) END FUNCTION '---------------------------------------------------- '---------------------------------------------------- SUB MakeIni(BYVAL inifile AS STRING) LOCAL ff AS LONG ff = FREEFILE OPEN inifile FOR OUTPUT AS #ff PRINT #ff, "# This is the first time you run the program:" PRINT #ff, "# please change the following settings, then" PRINT #ff, "# re-launch zrok launcher" PRINT #ff, "" PRINT #ff, "[ZrokSettings]" PRINT #ff, "zrok_param=share public localhost:80" PRINT #ff, "account_token=A1b2C3d4e5F6" PRINT #ff, "# The account token is needed when zrok gets stuck (happens frequently)" PRINT #ff, "ftp_upload=1" PRINT #ff, "# 1 to enable ftp upload ; 0 to disable it" PRINT #ff, "# if ftp_upload disabled, you can ignore the following sections PRINT #ff, "" PRINT #ff, "[TemplateToFill]" PRINT #ff, "source_file=""zrok launcher.php""" PRINT #ff, "replace_string=XXX" PRINT #ff, "# This string will be replaced with your zrok proxy url once assigned" PRINT #ff, "" PRINT #ff, "[UploadTo]" PRINT #ff, "ftp_target=/proxy/index.php" PRINT #ff, "ftp_server=ftp.mydomain.com" PRINT #ff, "ftp_username=mougino" PRINT #ff, "ftp_password=zrok_r0cks!" CLOSE #ff END SUB '---------------------------------------------------- '---------------------------------------------------- SUB GetIni() ' [ZrokSettings] g_zParam = GetIniS("zrok launcher.ini", "ZrokSettings", "zrok_param") g_AcoTkn = GetIniS("zrok launcher.ini", "ZrokSettings", "account_token") g_ftpUL = GetIniV("zrok launcher.ini", "ZrokSettings", "ftp_upload") ' [TemplateToFill] g_phpSrc = GetIniS("zrok launcher.ini", "TemplateToFill", "source_file") g_phpSrc = TRIM$(g_phpSrc, ANY $DQ+$SPC) g_phpRpl = GetIniS("zrok launcher.ini", "TemplateToFill", "replace_string") g_phpRpl = TRIM$(g_phpRpl, ANY $DQ+$SPC) ' [UploadTo] g_ftpTgt = GetIniS("zrok launcher.ini", "UploadTo", "ftp_target") g_ftpTgt = TRIM$(g_ftpTgt, ANY $DQ+$SPC) g_ftpSrv = GetIniS("zrok launcher.ini", "UploadTo", "ftp_server") g_ftpUsr = GetIniS("zrok launcher.ini", "UploadTo", "ftp_username") g_ftpPwd = GetIniS("zrok launcher.ini", "UploadTo", "ftp_password") 'CheckIni() ' Debug: show all parameters in a MsgBox END SUB '---------------------------------------------------- '---------------------------------------------------- SUB CheckIni() ?"[ZrokSettings]"+$CR _ +"zrok_param="+g_zParam+$CR _ +"account_token="+g_AcoTkn+$CR _ +"ftp_upload="+FORMAT$(g_ftpUL)+$CR _ +$CR _ +"[TemplateToFill]"+$CR _ +"source_file="+g_phpSrc+$CR _ +"replace_string="+g_phpRpl+$CR _ +$CR _ +"[UploadTo]"+$CR _ +"ftp_target="+g_ftpTgt+$CR _ +"ftp_server="+g_ftpSrv+$CR _ +"ftp_username="+g_ftpUsr+$CR _ +"ftp_password="+g_ftpPwd,,EXE.NAME$ END SUB '---------------------------------------------------- '---------------------------------------------------- SUB MakePhp(BYVAL inifile AS STRING) LOCAL ff AS LONG ff = FREEFILE OPEN inifile FOR OUTPUT AS #ff PRINT #ff, "" CLOSE #ff END SUB '---------------------------------------------------- '---------------------------------------------------- SUB LogMe(BYVAL e AS STRING) LOCAL ff AS LONG LOCAL t AS STRING ' Timestamp t = DATE$ t = "["+RIGHT$(t,4)+LEFT$(t,2)+MID$(t,4,2) t += "-"+REMOVE$(TIME$,":") t += ","+FORMAT$((TIMER*1000) MOD 1000, "000")+"] " ' Append to existing log ff = FREEFILE OPEN EXE.NAME$ + ".log" FOR APPEND AS #ff PRINT #ff, t + e CLOSE #ff END SUB '----------------------------------------------------